home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1994-96 Dimitrios P. Bouras and William K. W. Cheung
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the X Consortium shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from the X Consortium.
- *
- * Derived from the MIT X11R5 xbiff, written by Jim Fulton, which is
- * copyrighted (c) 1988 X Consortium.
- *
- * Mailbox XPM additions-modifications: Dimitrios P. Bouras
- * Audio support and XPM icon animation: William K. W. Cheung
- */
-
- #include <X11/IntrinsicP.h> /* for toolkit stuff */
- #include <X11/StringDefs.h> /* for useful atom names */
- #include <X11/cursorfont.h> /* for cursor constants */
- #include <X11/Xosdefs.h> /* for X_NOT_POSIX def */
- #include <sys/stat.h> /* for stat() ** needs types.h ***/
- #include <sys/signal.h> /* for signal() */
- #include <stdio.h> /* for printing error messages */
- #include <pwd.h> /* for getting username */
- #include <stdlib.h> /* for getenv() */
- #include <string.h>
-
- #ifndef NO_AUDIO
- #ifdef NCD_AUDIO
- #include <audio/audiolib.h>
- #include <audio/soundlib.h>
-
- static AuServer *aud; /* Audio server handler */
- #elif defined(RPLAY_AUDIO)
- #include <rplay.h>
- #endif /* ifdef NCD_AUDIO */
- #endif /* ifndef NO_AUDIO */
-
- #include <sys/file.h>
- #include <sys/fcntl.h>
- #include <sys/ioctl.h>
-
- #ifndef NO_AUDIO
- #ifdef SUN_AUDIO
-
- /* Adapted from <multimedia/audio_filehdr.h> */
-
- typedef unsigned u_32; /* we assume sizeof(unsigned) = 4 */
-
- typedef struct {
- u_32 magic; /* magic number */
- u_32 hdr_size; /* size of this header */
- u_32 data_size; /* length of data (optional) */
- u_32 encoding; /* data encoding format */
- u_32 sample_rate; /* samples per second */
- u_32 channels; /* number of interleaved channels */
- } Audio_filehdr;
-
- #if defined(linux) || defined(__FreeBSD__)
- #ifdef linux
- #include <linux/soundcard.h>
- #else
- #include <machine/soundcard.h>
- #endif /* ifdef linux */
-
- #define DEV_MIXER "/dev/mixer"
- #define MAX_VOLUME 100
- #define MIN_VOLUME 1
- #define RIGHT 0x01
- #define LEFT 0x02
-
- typedef struct stereovolume
- {
- unsigned char left;
- unsigned char right;
- unsigned char pad[2];
- } StereoVolume;
-
- void setvolume(int which, unsigned char setting, StereoVolume *volptr)
- {
- if ( setting < MIN_VOLUME )
- setting=MIN_VOLUME;
- if ( setting > MAX_VOLUME )
- setting=MAX_VOLUME;
-
- if ( which&RIGHT )
- volptr->right=setting;
- if ( which&LEFT )
- volptr->left=setting;
- }
- #else
- #include <sun/audioio.h>
- #endif /* if defined(linux) */
- #endif /* ifdef SUN_AUDIO */
- #endif /* ifndef NO_AUDIO */
-
- #ifndef X_NOT_POSIX
- #ifdef _POSIX_SOURCE
- # include <sys/wait.h>
- #else
- #define _POSIX_SOURCE
- # include <sys/wait.h>
- #undef _POSIX_SOURCE
- #endif
- # define waitCode(w) WEXITSTATUS(w)
- # define waitSig(w) WIFSIGNALED(w)
- typedef int waitType;
- # define INTWAITTYPE
- #else /* ! X_NOT_POSIX */
- #ifdef SYSV
- # define waitCode(w) (((w) >> 8) & 0x7f)
- # define waitSig(w) ((w) & 0xff)
- typedef int waitType;
- # define INTWAITTYPE
- #else
- # include <sys/wait.h>
- # define waitCode(w) ((w).w_T.w_Retcode)
- # define waitSig(w) ((w).w_T.w_Termsig)
- typedef union wait waitType;
- #endif /* SYSV else */
- #endif /* ! X_NOT_POSIX else */
-
- #include "xmail.xpm" /* for flag up (mail present) bits */
- #include "xnomail.xpm" /* for flag down (mail not here) */
-
- #ifndef min
- #define min(x,y) ((x) < (y)? (x): (y))
- #endif
-
- #include <X11/Xaw/XawInit.h>
- #include "MailboxP.h" /* for implementation mailbox stuff */
- #include <X11/Xmu/Drawing.h>
- #include <X11/extensions/shape.h>
-
- /*
- * The default user interface is to have the mailbox turn itself off whenever
- * the user presses a button in it. Expert users might want to make this
- * happen on EnterWindow. It might be nice to provide support for some sort of
- * exit callback so that you can do things like press q to quit.
- */
-
- static char defaultTranslations[] =
- "<ButtonPress>: unset()";
-
- static void Check(), Set(), Unset();
-
- static XtActionsRec actionsList[] = {
- { "check", Check },
- { "unset", Unset },
- { "set", Set },
- };
-
- /*
- * Storage for the XPM images for the two mailbox states.
- */
- static XpmImage mail_xpmimg[MAX_ANIM_IMAGE];
- static XpmImage nomail_xpmimg;
-
- /* Initialization of defaults */
-
- #define offset(field) XtOffsetOf(Mailbox_XPM_Rec, mailbox.field)
- #define goffset(field) XtOffsetOf(WidgetRec, core.field)
-
- static XtResource resources[] = {
- { XtNupdate, XtCInterval, XtRInt, sizeof (int),
- offset (update), XtRImmediate, (XtPointer)30 },
- { XtNfile, XtCFile, XtRString, sizeof (String),
- offset (filename), XtRString, NULL },
- { XtNcheckCommand, XtCCheckCommand, XtRString, sizeof(char*),
- offset (check_command), XtRString, NULL },
- { XtNvolume, XtCVolume, XtRInt, sizeof(int),
- offset (volume), XtRImmediate, (XtPointer)33 },
- { XtNonceOnly, XtCBoolean, XtRBoolean, sizeof(Boolean),
- offset (once_only), XtRImmediate, (XtPointer)False },
- { Nmailtool, CMailTool, XtRString, sizeof (String),
- offset (mail_tool), XtRString, NULL },
- { XtNmailAnimUpdate, XtCMailAnimUpdate, XtRInt, sizeof (int),
- offset (mail_animupdate), XtRImmediate, (XtPointer)1000 },
- { XtNmailAnimOnce, XtCMailAnimOnce, XtRBoolean, sizeof (Boolean),
- offset (mail_animonce), XtRImmediate, (XtPointer)False },
- { XtNmailNumOfXpmFile, XtCMailNumOfXpmFile, XtRInt, sizeof (int),
- offset (mail_numofxpmfile), XtRImmediate, (XtPointer)1 },
- { NmailXpmFile, CMailXpmFile, XtRString, sizeof (String),
- offset (mail_xpmfile), XtRString, NULL },
- { NnomailXpmFile, CNomailXpmFile, XtRString, sizeof (String),
- offset (nomail_xpmfile), XtRString, NULL },
- { NmailSndFile, CMailSndFile, XtRString, sizeof (String),
- offset (mail_sndfile), XtRString, NULL },
- { NmailSndComm, CMailSndComm, XtRString, sizeof (String),
- offset (mail_sndcomm), XtRString, NULL },
- };
-
- #undef offset
-
- static void GetMailFile(), CloseDown(), ReadIconFile(), DefaultXpmImage();
- static void check_mailbox(), redraw_mailbox(), beep();
- static void Initialize(), Realize(), Destroy(), Redisplay();
- static Boolean SetValues();
-
- Mailbox_XPM_ClassRec mailboxClassRec = {
- { /* core fields */
- /* superclass */ (WidgetClass) &simpleClassRec,
- /* class_name */ "Mailbox",
- /* widget_size */ sizeof(Mailbox_XPM_Rec),
- /* class_initialize */ XawInitializeWidgetSet,
- /* class_part_initialize */ NULL,
- /* class_inited */ FALSE,
- /* initialize */ Initialize,
- /* initialize_hook */ NULL,
- /* realize */ Realize,
- /* actions */ actionsList,
- /* num_actions */ XtNumber(actionsList),
- /* resources */ resources,
- /* resource_count */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
- /* compress_enterleave */ TRUE,
- /* visible_interest */ FALSE,
- /* destroy */ Destroy,
- /* resize */ NULL,
- /* expose */ Redisplay,
- /* set_values */ SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_private */ NULL,
- /* tm_table */ defaultTranslations,
- /* query_geometry */ XtInheritQueryGeometry,
- /* display_accelerator */ XtInheritDisplayAccelerator,
- /* extension */ NULL
- },
- { /* simple fields */
- /* change_sensitive */ XtInheritChangeSensitive
- },
- { /* mailbox fields */
- /* ignore */ 0
- }
- };
-
- WidgetClass mailboxWidgetClass = (WidgetClass) &mailboxClassRec;
-
-
- /*
- * widget initialization
- */
-
- static GC get_mailbox_gc (w)
- MailboxWidget w;
- {
- XtGCMask valuemask;
- XGCValues xgcv;
-
- valuemask = GCFunction | GCGraphicsExposures;
- xgcv.function = GXcopy;
- xgcv.graphics_exposures = False; /* this is Bool, not Boolean */
- return (XtGetGC ((Widget) w, valuemask, &xgcv));
- }
-
- int zombiekiller()
- {
- int status;
-
- while (wait3(&status, WNOHANG, 0) >= 0);
- #ifdef linux
- signal(SIGCHLD, (SignalHandler)zombiekiller);
- #endif
- }
-
- /* ARGSUSED */
- static void Initialize (request, new)
- Widget request, new;
- {
- MailboxWidget w = (MailboxWidget) new;
- int shape_event_base, shape_error_base;
-
- #ifdef SYSV
- signal(SIGCLD, zombiekiller);
- #elif defined(linux)
- signal(SIGCHLD, (SignalHandler)zombiekiller);
- #else
- signal(SIGCHLD, zombiekiller);
- #endif
-
- if ( !XShapeQueryExtension (XtDisplay (w), &shape_event_base,
- &shape_error_base)) {
- fprintf (stderr, "%s: shape extensions not supported!\n",
- "Mailbox widget");
- CloseDown (w, 1);
- }
-
- w->mailbox.shape_cache.mask = None;
- w->mailbox.gc = get_mailbox_gc (w);
- w->mailbox.interval_id = (XtIntervalId) 0;
- w->mailbox.anim_int_id = (XtIntervalId) -1;
- w->mailbox.first_trig = 1;
- w->mailbox.flag_up = FALSE;
- w->mailbox.last_size = 0;
- w->mailbox.anim_id = 0;
-
- if ((w->mailbox.mail_numofxpmfile < 1)
- || (w->mailbox.mail_numofxpmfile > MAX_ANIM_IMAGE)) {
- fprintf (stderr,
- "%s: Number of Xpm Images must be between 1 and 8 !\n",
- "Mailbox widget");
- CloseDown (w, 1);
- }
-
- if (!w->mailbox.filename) GetMailFile (w);
-
- /*
- * read the XPM files from the resources, if any, and create
- * XpmImages, or create XpmImages from default image data
- */
-
- w->mailbox.full[0].xpmimg = None;
- if (w->mailbox.mail_xpmfile) ReadIconFile(w, True);
- if (w->mailbox.full[0].xpmimg == None) DefaultXpmImage(w, True);
-
- w->mailbox.empty.xpmimg = None;
- if (w->mailbox.nomail_xpmfile) ReadIconFile(w, False);
- if (w->mailbox.empty.xpmimg == None) DefaultXpmImage(w, False);
-
- #define _MAX(x,y) ((x>y)?x:y)
- w->core.width = _MAX( w->mailbox.full[0].width, w->mailbox.empty.width);
- w->core.height = _MAX( w->mailbox.full[0].height, w->mailbox.empty.height);
- #undef _MAX
-
- return;
- }
-
-
- /*
- * action procedures
- */
-
- /*
- * pretend there is new mail; put widget in flagup state
- */
-
- /* ARGSUSED */
- static void Set (gw, event, params, nparams)
- Widget gw;
- XEvent *event;
- String *params;
- Cardinal *nparams;
- {
- MailboxWidget w = (MailboxWidget) gw;
-
- w->mailbox.last_size = -1;
-
- check_mailbox (w, TRUE, FALSE); /* redraw, no reset */
-
- return;
- }
-
-
- /*
- * ack the existing mail; put widget in flagdown state
- */
-
- /* ARGSUSED */
- static void Unset (gw, event, params, nparams)
- Widget gw;
- XEvent *event;
- String *params;
- Cardinal *nparams;
- {
- MailboxWidget w = (MailboxWidget) gw;
-
- check_mailbox (w, TRUE, TRUE); /* redraw, reset */
-
- return;
- }
-
-
- /*
- * look to see if there is new mail; if so, Set, else Unset
- */
-
- /* ARGSUSED */
- static void Check (gw, event, params, nparams)
- Widget gw;
- XEvent *event;
- String *params;
- Cardinal *nparams;
- {
- MailboxWidget w = (MailboxWidget) gw;
-
- check_mailbox (w, TRUE, FALSE); /* redraw, no reset */
-
- return;
- }
-
-
- /* ARGSUSED */
- static void clock_tic_anim (client_data, id)
- XtPointer client_data;
- XtIntervalId *id;
- {
- MailboxWidget w = (MailboxWidget) client_data;
-
- redraw_mailbox(w);
- /*
- * and reset the timer
- */
-
- w->mailbox.anim_int_id =
- XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w),
- w->mailbox.mail_animupdate, clock_tic_anim, client_data);
-
- return;
- }
-
- /* ARGSUSED */
- static void clock_tic (client_data, id)
- XtPointer client_data;
- XtIntervalId *id;
- {
- MailboxWidget w = (MailboxWidget) client_data;
-
- check_mailbox (w, FALSE, FALSE); /* no redraw, no reset */
-
- /*
- * and reset the timer
- */
-
- w->mailbox.interval_id =
- XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w),
- w->mailbox.update * 1000, clock_tic, client_data);
-
- return;
- }
-
- static void Realize (gw, valuemaskp, attr)
- Widget gw;
- XtValueMask *valuemaskp;
- XSetWindowAttributes *attr;
- {
- MailboxWidget w = (MailboxWidget) gw;
- register Display *dpy = XtDisplay (w);
- XpmAttributes xpm_attr;
- int i;
-
- *valuemaskp |= (CWBitGravity | CWCursor);
- attr->bit_gravity = ForgetGravity;
- attr->cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
-
- (*mailboxWidgetClass->core_class.superclass->core_class.realize)
- (gw, valuemaskp, attr);
-
- /*
- * build the pixmaps for the two mailbox
- * states from the saved XpmImages
- */
- xpm_attr.valuemask = 0;
-
- for(i = 0; i < w->mailbox.mail_numofxpmfile; i++) {
- XpmCreatePixmapFromXpmImage (dpy, w->core.window,
- w->mailbox.full[i].xpmimg,
- &w->mailbox.full[i].pixmap,
- &w->mailbox.full[i].bitmap, &xpm_attr);
- }
-
- xpm_attr.valuemask = 0;
- XpmCreatePixmapFromXpmImage (dpy, w->core.window, w->mailbox.empty.xpmimg,
- &w->mailbox.empty.pixmap,
- &w->mailbox.empty.bitmap, &xpm_attr);
-
- w->mailbox.interval_id =
- XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) w),
- w->mailbox.update * 1000, clock_tic, (XtPointer) w);
-
- w->mailbox.shape_cache.mask = None;
-
- check_mailbox (w, TRUE, FALSE);
-
- return;
- }
-
-
- static void Destroy (gw)
- Widget gw;
- {
- MailboxWidget w = (MailboxWidget) gw;
- Display *dpy = XtDisplay (gw);
- int i;
-
- XtFree (w->mailbox.filename);
- if (w->mailbox.interval_id) XtRemoveTimeOut (w->mailbox.interval_id);
- if (w->mailbox.anim_int_id != -1) XtRemoveTimeOut (w->mailbox.anim_int_id);
- XtReleaseGC(gw, w->mailbox.gc);
- #define freepix(p) if (p) XFreePixmap (dpy, p)
- for(i = 0; i < w->mailbox.mail_numofxpmfile; i++) {
- freepix (w->mailbox.full[i].bitmap); /* until cvter does ref cnt */
- freepix (w->mailbox.full[i].pixmap);
- }
- freepix (w->mailbox.empty.bitmap); /* until cvter does ref cnt */
- freepix (w->mailbox.empty.pixmap);
- freepix (w->mailbox.shape_cache.mask);
- #undef freepix
- return;
- }
-
-
- static void Redisplay (gw)
- Widget gw;
- {
- MailboxWidget w = (MailboxWidget) gw;
-
- check_mailbox (w, TRUE, FALSE);
- }
-
-
- static void check_mailbox (w, force_redraw, reset)
- MailboxWidget w;
- Boolean force_redraw, reset;
- {
- long mailboxsize = 0;
- Boolean readSinceLastWrite = FALSE;
- int pid;
-
- if (w->mailbox.check_command != NULL) {
- waitType wait_status;
- int check_status;
- #ifdef INTWAITTYPE
- wait_status = system(w->mailbox.check_command);
- #else
- wait_status.w_status = system(w->mailbox.check_command);
- #endif
- check_status = waitCode(wait_status);
-
- /* error in sh checkCommand execution */
- if (waitSig(wait_status))
- check_status = 2; /* act as if there is no mail */
-
- switch (check_status) {
- case 0:
- mailboxsize = w->mailbox.last_size + 1;
- break;
- case 2:
- mailboxsize = 0;
- break;
- default: /* treat everything else as no change */
- /* case 1 is no change */
- mailboxsize = w->mailbox.last_size;
- }
- } else {
- struct stat st;
- if (stat (w->mailbox.filename, &st) == 0) {
- mailboxsize = st.st_size;
- readSinceLastWrite = (st.st_atime > st.st_mtime);
- }
- }
-
- /*
- * Now check for changes. If reset is set then we want to pretent that
- * there is no mail. If the mailbox is empty then we want to turn off
- * the flag. Otherwise if the mailbox has changed size then we want to
- * put the flag up, unless the mailbox has been read since the last
- * write.
- *
- * The cases are:
- * o forced reset by user DOWN
- * o no mailbox or empty (zero-sized) mailbox DOWN
- * o if read after most recent write DOWN
- * o same size as last time no change
- * o bigger than last time UP
- * o smaller than last time but non-zero UP
- *
- * The last two cases can be expressed as different from last
- * time and non-zero.
- */
-
- if (reset) { /* forced reset */
- w->mailbox.flag_up = FALSE;
- force_redraw = TRUE;
- if (w->mailbox.mail_tool) {
- pid = fork();
- if (pid == 0) { /* Child process */
- system(w->mailbox.mail_tool);
- _exit(0);
- }
- }
- } else if (mailboxsize == 0) { /* no mailbox or empty */
- w->mailbox.flag_up = FALSE;
- if (w->mailbox.last_size > 0)
- force_redraw = TRUE; /* if change */
- } else if (readSinceLastWrite) { /* only when checkCommand is NULL */
- /* mailbox has been read after most recent write */
- if (w->mailbox.flag_up) {
- w->mailbox.flag_up = FALSE;
- force_redraw = TRUE;
- }
- } else if (mailboxsize != w->mailbox.last_size) { /* different size */
- if (!w->mailbox.once_only || !w->mailbox.flag_up)
- beep(w);
- if (!w->mailbox.flag_up)
- force_redraw = w->mailbox.flag_up = TRUE;
- }
- w->mailbox.last_size = mailboxsize;
- if (force_redraw) redraw_mailbox (w);
- return;
- }
-
- /*
- * get user name for building mailbox
- */
-
- static void GetMailFile (w)
- MailboxWidget w;
- {
- char *getlogin();
- char *username;
-
- /* MAIL env var overrides any hard-coded mail dir */
- username = getenv( "MAIL" );
- if (username!=(char *)NULL) {
- w->mailbox.filename = (String) XtMalloc (strlen (username) + 1);
- strcpy (w->mailbox.filename, username);
- return;
- }
-
- username = getlogin();
- if (!username) {
- struct passwd *pw = getpwuid (getuid ());
-
- if (!pw) {
- fprintf (stderr, "%s: unable to find a username for you.\n",
- "Mailbox widget");
- CloseDown (w, 1);
- }
- username = pw->pw_name;
- }
- w->mailbox.filename = (String) XtMalloc (strlen (MAILBOX_DIRECTORY) + 1 +
- strlen (username) + 1);
- strcpy (w->mailbox.filename, MAILBOX_DIRECTORY);
- strcat (w->mailbox.filename, "/");
- strcat (w->mailbox.filename, username);
- return;
- }
-
- static void CloseDown (w, status)
- MailboxWidget w;
- int status;
- {
- Display *dpy = XtDisplay (w);
-
- XtDestroyWidget ((Widget)w);
- XCloseDisplay (dpy);
- exit (status);
- }
-
- /*
- * Called by Initialize() to read XPM icon files
- * and create XPM image data from their contents
- */
- static void ReadIconFile (w, flag)
- MailboxWidget w;
- Bool flag;
- {
- String name;
- char aname[255], *ch=NULL;
- int code;
- struct _mbimage *im;
- XpmImage *imp;
- int i;
-
- if ( flag ) {
- if (w->mailbox.mail_numofxpmfile > 1) {
- /* append a number before a file name */
- ch = strrchr(w->mailbox.mail_xpmfile, '/');
- if (ch) *ch = '\0';
- }
- for(i = 0; i < w->mailbox.mail_numofxpmfile; i++) {
- if (w->mailbox.mail_numofxpmfile > 1)
- sprintf(aname, "%s/%d%s", w->mailbox.mail_xpmfile, i, ch+1);
- else
- strcpy(aname, w->mailbox.mail_xpmfile); /* 1: file for "mail" */
- im = &w->mailbox.full[i];
- imp = &mail_xpmimg[i];
- code = XpmReadFileToXpmImage( aname, imp, (XpmInfo *)NULL );
- if ( code == XpmSuccess ) {
- im->xpmimg = imp;
- im->width = imp->width;
- im->height = imp->height;
- }
- else
- {
- fprintf (stderr, "%s: ReadIconFile(%s): %s\n",
- "Mailbox widget", aname, XpmGetErrorString(code));
- w->mailbox.mail_numofxpmfile = i;
- if (w->mailbox.mail_numofxpmfile == 0)
- w->mailbox.mail_numofxpmfile = 1;
- break;
- }
- }
- }
- else {
- name = w->mailbox.nomail_xpmfile; /* False: file for no "mail" */
- im = &w->mailbox.empty;
- imp = &nomail_xpmimg;
- code = XpmReadFileToXpmImage( name, imp, (XpmInfo *)NULL );
- if ( code == XpmSuccess ) {
- im->xpmimg = imp;
- im->width = imp->width;
- im->height = imp->height;
- }
- else
- fprintf (stderr, "%s: ReadIconFile(%s): %s\n",
- "Mailbox widget", name, XpmGetErrorString(code));
- }
- }
-
- /*
- * Called by Initialize() to create XPM image
- * data from the default (hard-coded) XPM icons
- */
- static void DefaultXpmImage(w, flag)
- MailboxWidget w;
- Bool flag;
- {
- #define MakeXpmImage() { \
- code = XpmCreateXpmImageFromData (datap, imp, (XpmInfo *)NULL); \
- if ( code == XpmSuccess ) { \
- im->xpmimg = imp; \
- im->width = imp->width; \
- im->height = imp->height; \
- } \
- else { \
- fprintf (stderr, "%s: DefaultXpmImage(): %s\n", \
- "Mailbox widget", XpmGetErrorString(code)); \
- CloseDown (w, 1); \
- } \
- }
-
- char **datap;
- int code;
- struct _mbimage *im;
- XpmImage *imp;
- int i;
-
- if ( flag ) {
- for(i = 0; i < w->mailbox.mail_numofxpmfile; i++) {
- datap = (i % 2)? xnomail_xpm: xmail_xpm; /* 1: data for "mail" */
- im = &w->mailbox.full[i];
- imp = &mail_xpmimg[i];
- MakeXpmImage();
- }
- }
- else {
- datap = xnomail_xpm; /* False: data for "no mail" */
- im = &w->mailbox.empty;
- imp = &nomail_xpmimg;
- MakeXpmImage();
- }
- #undef MakeXpmImage
- }
-
- /* ARGSUSED */
- static Boolean SetValues (gcurrent, grequest, gnew)
- Widget gcurrent, grequest, gnew;
- {
- MailboxWidget current = (MailboxWidget) gcurrent;
- MailboxWidget new = (MailboxWidget) gnew;
- Boolean redisplay = FALSE;
-
- if (current->mailbox.update != new->mailbox.update) {
- if (current->mailbox.interval_id)
- XtRemoveTimeOut (current->mailbox.interval_id);
- new->mailbox.interval_id =
- XtAppAddTimeOut (XtWidgetToApplicationContext(gnew),
- new->mailbox.update * 1000, clock_tic,
- (XtPointer) gnew);
- }
-
- return (redisplay);
- }
-
-
- /*
- * drawing code
- */
-
- static void redraw_mailbox (w)
- MailboxWidget w;
- {
- static int ctrig=0;
- register Display *dpy = XtDisplay (w);
- register Window win = XtWindow (w);
- GC gc = w->mailbox.gc;
- struct _mbimage *im;
- Widget parent;
-
- if (w->mailbox.flag_up) { /* draw the "mail" icon */
- if (w->mailbox.mail_numofxpmfile > 1) {
- if (w->mailbox.first_trig) {
- w->mailbox.anim_int_id = XtAppAddTimeOut (
- XtWidgetToApplicationContext((Widget) w),
- w->mailbox.mail_animupdate, clock_tic_anim,
- (XtPointer) w);
- w->mailbox.anim_id = 0;
- w->mailbox.first_trig = 0;
- ctrig = 0;
- } else {
- /* This route called twice (The second one from ReDisplay()) */
- if ((++ctrig % 2) == 0) {
- w->mailbox.anim_id = (w->mailbox.anim_id + 1)
- % (w->mailbox.mail_numofxpmfile);
- if (w->mailbox.mail_animonce && (w->mailbox.anim_id == 0)) {
- if (w->mailbox.anim_int_id != -1) {
- XtRemoveTimeOut(w->mailbox.anim_int_id);
- w->mailbox.anim_int_id = -1;
- }
- w->mailbox.anim_id = w->mailbox.mail_numofxpmfile - 1;
- }
- ctrig = 0;
- }
-
- if (w->mailbox.anim_int_id == -1)
- return;
- }
- im = &(w->mailbox.full[w->mailbox.anim_id]);
- }
- else im = &(w->mailbox.full[0]);
- } else { /* draw the "no mail" icon */
- im = &w->mailbox.empty;
- w->mailbox.first_trig = 1;
- if (w->mailbox.anim_int_id != -1) {
- XtRemoveTimeOut(w->mailbox.anim_int_id);
- w->mailbox.anim_int_id = -1;
- }
- }
- XClearWindow (dpy, win);
- XCopyArea (dpy, im->pixmap, win, gc, 0, 0, im->width, im->height, 0, 0);
-
- /*
- * XXX - temporary hack; walk up widget tree to find top most parent (which
- * will be a shell) and mash it to have our shape. This will be replaced
- * by a special shell widget.
- */
-
- for (parent = (Widget) w; XtParent(parent);
- parent = XtParent(parent));
-
- if (im->bitmap != w->mailbox.shape_cache.mask) {
- XShapeCombineMask (XtDisplay(parent), XtWindow(parent),
- ShapeBounding, 0, 0, im->bitmap, ShapeSet);
- w->mailbox.shape_cache.mask = im->bitmap;
- }
-
- return;
- }
-
- #ifdef COM_AUDIO
- static int comm_play (command, soundfile)
- char *command;
- char *soundfile;
- {
- char comm[255]; /* we suppose the command will be smaller than 255 chars */
- int result;
-
- if ( ( command == NULL ) || ( soundfile == NULL ) )
- return -1;
-
- sprintf(comm, command, soundfile);
-
- return system(comm);
- }
- #endif /* COM_AUDIO */
-
- #ifndef NO_AUDIO
- #define CLOSE_FD(afd) { if (afd > -1) close(afd); afd = -1; }
-
- #if defined(linux) || defined(__FreeBSD__)
- #define INIT_FD { audiofd = filefd = mixer_fd = -1; }
- #define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); CLOSE_FD(mixer_fd); return; }
- #else
- #define INIT_FD { audiofd = filefd = 0; }
- #define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); return; }
- #endif /* if defined(linux) */
- #endif /* ifndef NO_AUDIO */
-
- static void beep (w)
- MailboxWidget w;
- {
- #ifndef NO_AUDIO
- #ifdef COM_AUDIO
- if (comm_play(w->mailbox.mail_sndcomm, w->mailbox.mail_sndfile))
- #else
- #ifdef NCD_AUDIO
- char *auservername = NULL;
- #elif defined(RPLAY_AUDIO)
- char *rplay_name;
- #endif /* ifdef NCD_AUDIO */
- int audiofd, filefd;
- int rn, wn, len;
- unsigned char buf[256];
- #ifdef SUN_AUDIO
- Audio_filehdr *au_hdr;
- #if defined(linux) || defined(__FreeBSD__)
- StereoVolume origVol, volume;
- int mixer_fd;
- #else
- audio_info_t ais;
- int origVol;
- #endif /* if defined(linux) */
- #endif /* ifdef SUN_AUDIO */
-
- if (w->mailbox.mail_sndfile) {
- #ifdef NCD_AUDIO
- aud = AuOpenServer(auservername, 0, NULL, 0, NULL, NULL);
- if (aud) {
- if (!AuSoundPlaySynchronousFromFile(aud, w->mailbox.mail_sndfile,
- w->mailbox.volume))
- fprintf(stderr, "%s: Couldn't play file \"%s\"\n",
- "Mailbox widget", w->mailbox.mail_sndfile);
-
- AuCloseServer(aud);
- return;
- }
- #elif defined(RPLAY_AUDIO)
- rplay_name = rplay_default_host();
- if (rplay_host_volume(rplay_name, w->mailbox.mail_sndfile,
- (int)(w->mailbox.volume*2.55)) < 0)
- fprintf(stderr, "%s: Rplay couldn't play file \"%s\"\n",
- "Mailbox widget", w->mailbox.mail_sndfile);
- else
- return;
- #endif /* ifdef NCD_AUDIO */
- #ifdef SUN_AUDIO
- INIT_FD;
- audiofd = open( "/dev/audio", O_WRONLY | O_NDELAY );
- if (audiofd < 0) {
- fprintf(stderr, "%s: Problem opening /dev/audio.\n",
- "Mailbox widget");
- END_FD;
- }
- #if defined(linux) || defined(__FreeBSD__)
- if ( (mixer_fd=open(DEV_MIXER, O_RDWR, 0)) < 0 ) {
- fprintf(stderr, "Can't open %s: ", DEV_MIXER);
- END_FD;
- }
-
- if ( ioctl(mixer_fd, SOUND_MIXER_READ_PCM, &origVol) < 0 ) {
- perror("Can't obtain current volume settings");
- END_FD;
- }
-
- setvolume(LEFT|RIGHT, (unsigned char)w->mailbox.volume, &volume);
-
- if ( ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, &volume) < 0 ) {
- fprintf(stderr, "Can't set current volume settings");
- END_FD;
- }
-
- /* The following is required for the setting to take into effect
- CLOSE_FD(mixer_fd); */
- #else
- if( ioctl( audiofd, AUDIO_GETINFO, &ais ) ) {
- fprintf(stderr, "%s: Problem retrieving /dev/audio info.\n",
- "Mailbox widget");
- END_FD;
- }
- origVol = ais.play.gain;
- ais.play.gain = w->mailbox.volume;
- if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) {
- fprintf(stderr, "%s: Problem setting /dev/audio info.\n",
- "Mailbox widget");
- END_FD;
- }
- #endif /* if defined(linux) */
- filefd = open(w->mailbox.mail_sndfile, O_RDONLY);
- if (filefd < 0) {
- fprintf(stderr, "%s: Couldn't play file \"%s\"\n",
- "Mailbox widget", w->mailbox.mail_sndfile);
- END_FD;
- }
-
- /* Read in the audio header */
- rn = read(filefd, buf, sizeof(Audio_filehdr));
-
- if (rn > 0 && strncmp(buf, ".snd", 4) != 0) {
- fprintf(stderr, "%s: Invalid audio file format.\n",
- "Mailbox widget");
- END_FD;
- }
-
- /* Strip the header */
- au_hdr = (Audio_filehdr *)buf;
- #if defined(linux) || defined(__FreeBSD__)
- rn = ntohl(au_hdr->hdr_size) - sizeof(Audio_filehdr);
- #else
- rn = au_hdr->hdr_size - sizeof(Audio_filehdr);
- #endif /* if defined(linux) */
- for( ; rn > 0; ) {
- len = min(rn, sizeof(buf));
- len = read(filefd, buf, len);
- rn -= len;
- }
-
- while(1) {
- rn = read(filefd, buf, sizeof(buf));
- if (rn < 0) {
- fprintf(stderr, "%s: Error reading from file \"%s\"\n",
- "Mailbox widget", w->mailbox.mail_sndfile);
- END_FD;
- }
- if (rn == 0)
- break;
- while(1) {
- wn = write(audiofd, buf, rn);
- if ( wn < 0 ) {
- fprintf(stderr, "%s: Error writing to /dev/audio.\n",
- "Mailbox widget");
- END_FD;
- }
- if ( wn != 0 )
- break;
- usleep(1000);
- }
- }
- #if defined(linux) || defined(__FreeBSD__)
- CLOSE_FD(audiofd);
-
- if ( ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, &origVol) < 0 ) {
- fprintf(stderr, "Can't reset volume settings");
- }
- #else
- ais.play.gain = origVol;
- if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) {
- fprintf(stderr, "%s: Problem setting /dev/audio info.\n",
- "Mailbox widget");
- }
- #endif /* if defined(linux) */
- END_FD;
- #endif /* #ifdef SUN_AUDIO */
- }
- else
- #endif /* #ifdef COM_AUDIO */
- #endif /* #ifndef NO_AUDIO */
- XBell (XtDisplay (w), w->mailbox.volume);
- return;
- }
-
-